home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / sources.lha / sources / sys / gc.t < prev    next >
Text File  |  1988-02-05  |  21KB  |  528 lines

  1. (herald gc
  2.   (env tsys
  3.        (osys table)       ;; %TABLE-VECTOR must be integrated here
  4.        (osys gc_weak)))   ;; for the GC-WEAK-???-LISTs
  5.  
  6. ;;; Copyright (c) 1985 Yale University
  7. ;;;     Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
  8. ;;; This material was developed by the T Project at the Yale University Computer 
  9. ;;; Science Department.  Permission to copy this software, to redistribute it, 
  10. ;;; and to use it for any purpose is granted, subject to the following restric-
  11. ;;; tions and understandings.
  12. ;;; 1. Any copy made of this software must include this copyright notice in full.
  13. ;;; 2. Users of this software agree to make their best efforts (a) to return
  14. ;;;    to the T Project at Yale any improvements or extensions that they make,
  15. ;;;    so that these may be included in future releases; and (b) to inform
  16. ;;;    the T Project of noteworthy uses of this software.
  17. ;;; 3. All materials developed as a consequence of the use of this software
  18. ;;;    shall duly acknowledge such use, in accordance with the usual standards
  19. ;;;    of acknowledging credit in academic research.
  20. ;;; 4. Yale has made no warrantee or representation that the operation of
  21. ;;;    this software will be error-free, and Yale is under no obligation to
  22. ;;;    provide any services, by way of maintenance, update, or otherwise.
  23. ;;; 5. In conjunction with products arising from the use of this material,
  24. ;;;    there shall be no use of the name of the Yale University nor of any
  25. ;;;    adaptation thereof in any advertising, promotional, or sales literature
  26. ;;;    without prior written consent from Yale in each case.
  27. ;;;
  28.  
  29. ;;; T 3.0 garbage collector, based on Clark's algorithm.
  30. ;;; Tested using a simulated memory.  See GCTEST.T, GCSIM.T, etc.
  31. ;;;
  32. ;;; For a description of the algorithm and related information see
  33. ;;; GC.DOC. For a description of T3 data representations see DATA.DOC.
  34. ;;;
  35. ;;; ***Important***
  36. ;;;    The first two slots in a closure cannot contain closure
  37. ;;;    internal closures.  There cannot be pointers into either
  38. ;;;    of the first two slots of any extend that contains pointers.
  39. ;;;    This is because those slots are used to hold back pointers
  40. ;;;    during GC.
  41. ;;;
  42. ;;; The following procedures are needed for MOVE-OBJECT to run:
  43. ;;;
  44. ;;;    (K-LIST)
  45. ;;;        A global variable that cannot be a variable because of circularity
  46. ;;;        problems.  This is a list of unfinished objects, linked in a list
  47. ;;;        in the old heap.  It is a pseudonym for (PROCESS-GLOBAL TASK/K-LIST).
  48. ;;;    (DESCRIPTOR->FIXNUM pointer)
  49. ;;;        Change a descriptor to a fixnum by clobbering the tag.
  50. ;;;    (DESCRIPTOR-TAG pointer)
  51. ;;;        Returns the type tag of POINTER.
  52. ;;;    (CLOSURE? obj)
  53. ;;;        Is OBJ a closure?
  54. ;;;    (TEMPLATE-HEADER? header)
  55. ;;;        Is HEADER the header of a template?
  56. ;;;    (EXTEND-ELT extend offset)
  57. ;;;        The contents of EXTEND + OFFSET(in zero based longwords).  This is
  58. ;;;        settable.
  59. ;;;    (EXTEND-HEADER extend)
  60. ;;;        Returns the header of EXTEND i.e. (EXTEND-ELT EXTEND -1)
  61. ;;;    (HEADER-TYPE header)
  62. ;;;        The type field of an extend header.
  63. ;;;    (MAKE-POINTER pointer offset)
  64. ;;;        Returns a pointer to POINTER + OFFSET.
  65. ;;;    (GC-EXTEND->PAIR extend)
  66. ;;;    (GC-PAIR->EXTEND pair)
  67. ;;;        Change the type tag as indicated.
  68. ;;;    *OLD-SPACE-BEGIN*
  69. ;;;    *OLD-SPACE-FRONTIER*
  70. ;;;        The limits of old-space (these are fixnums).
  71. ;;;    (IN-NEW-SPACE? obj)
  72. ;;;        Is OBJ within new-space.
  73. ;;;    (CLOSURE-ENCLOSING-OBJECT <closure-pointer>)
  74. ;;;    (CLOSURE-ENCLOSER-OFFSET  <closure-pointer>)
  75. ;;;    (TEMPLATE-ENCLOSING-OBJECT <template-pointer>)  
  76. ;;;    (TEMPLATE-ENCLOSER-OFFSET  <template-pointer>)      
  77. ;;;    (TEMPLATE-POINTER-SLOTS    <template-pointer>)        
  78. ;;;    (TEMPLATE-SCRATCH-SLOTS    <template-pointer>)        
  79. ;;;    (TEMPLATE-INTERNAL-BIT?    <template-pointer>)        
  80. ;;;    HEADER/...
  81. ;;;
  82. ;;;      Simulator procedures that must shadow definitions in this file:
  83. ;;;    K-LIST
  84. ;;;        
  85. ;;;    (GC-COPY-PAIR pair) 
  86. ;;;        Copies PAIR into new space, putting a forwarding pointer in the cdr.
  87. ;;;    (GC-COPY-EXTEND obj size)
  88. ;;;        Copies an extend into new space.  OBJ is the extend, SIZE is the
  89. ;;;        length.  A forwarding pointer is put in the header of OBJ.
  90. ;;;    (GC-ERROR-MESSAGE string loc)
  91. ;;;        Print an error message.
  92. ;;;
  93. ;;;      Simulator procedures that must shadow definitions in T system:
  94. ;;;    CAR, CDR, LIST?, EXTEND?, VECTOR-LENGTH, NULL?,
  95. ;;;    IMMEDIATE?, TEMPLATE?, BYTEV?, BYTEV-LENGTH?
  96.  
  97. ;;; 3/14/86:
  98. ;;;  Flushed statistics other than the object count.
  99. ;;;  MOVE-OBJECT does the range check before anything else.
  100. ;;;  Old-space limits are in variables and not in a structure.
  101.  
  102. ;;; To do:
  103. ;;;  Vcells and weaks flushed in favor of weak-sets, weak-alists and
  104. ;;;    weak-tables.
  105.  
  106. ;;;   The top level procedure.  O-LOC is an extend containing a pointer to the
  107. ;;; object to be copied.  This is overwritten by a pointer to the new copy.
  108. ;;;   This procedure dispatches on the tag.  Nonpointers and nonrelocating
  109. ;;; pointers are left alone.  Pairs are checked to see if the cdr contains a
  110. ;;; forwarding pointer.  Extends require further dispatch.  The M68000 requires
  111. ;;; the TEMPLATE-HEADER? check first since the other extend tests are not
  112. ;;; valid on templates.  Extends are then checked for a forwarding pointer.
  113.  
  114. (define (move-object o-loc)
  115.   (let* ((obj (extend-header o-loc))
  116.          (fxobj (descriptor->fixnum obj)))
  117.     (if (not (and (fx>= fxobj *old-space-begin*)
  118.                   (fx< fxobj *old-space-frontier*)))
  119.         (pop-k-list)
  120.         (xselect (descriptor-tag obj)
  121.           ((tag/fixnum tag/immediate)
  122.            (pop-k-list))
  123.           ((tag/pair)
  124.            (cond ((and (list? (cdr obj)) ; This is a safety check
  125.                        (in-new-space? (cdr obj)))
  126.                   (set (extend-header o-loc) (cdr obj))
  127.                   (pop-k-list))
  128.                  (else
  129.                   (move-pair obj o-loc))))
  130.           ((tag/extend)
  131.            (let ((header (extend-header obj)))
  132.              (cond ((template-header? header)   ; 68000 requires this first
  133.                     (move-template obj o-loc))
  134.                    ((extend? header)
  135.                     (cond ((in-new-space? header)
  136.                            (set (extend-header o-loc) (extend-header obj))
  137.                            (pop-k-list))
  138.                           ((template? header)
  139.                            (move-closure obj o-loc))
  140.                           (else
  141.                            (gc-error-message "header is a non-template extend" o-loc)
  142.                            (pop-k-list))))
  143.                    ((immediate? header)
  144.                     (move-immediate-object obj o-loc))
  145.                    (else
  146.                     (gc-error-message "corrupt header" o-loc)
  147.                     (pop-k-list)))))))))
  148.  
  149. ;;;   The K-LIST is a list of partially copied objects that are linked together
  150. ;;; in old space.  This cannot be a normal global variable as the GC would
  151. ;;; attempt to move it into new space.
  152.  
  153. (define-constant k-list
  154.   (object (lambda ()
  155.             (process-global task/k-list))
  156.     ((setter self)
  157.      (lambda (k)
  158.        (set (process-global task/k-list) k)))))
  159.  
  160. ;;;   Pop the next thing off the list and move it.  If it is a pair,
  161. ;;; remove it from the K-list and call MOVE-OBJECT to copy the cdr.
  162. ;;; Otherwise, (extend-elt K 1) contains the index of the next pointer
  163. ;;; to be copied. If there are none to be copied then remove the
  164. ;;; extend from the K-list and recur; otherwise, decrement the
  165. ;;; pointer and call MOVE-OBJECT to do the copying.
  166.  
  167. (define (pop-k-list)
  168.   (let ((next (k-list)))
  169.     (cond ((null? next)
  170.            '#t)   ; The only (non-error) return in the GC.
  171.           ((list? next)
  172.            (let* ((fwd (cdr next))
  173.                   (to-copy (if (list? fwd) (gc-pair->extend fwd) fwd)))
  174.              (set (k-list) (car next))
  175.              (move-object (make-pointer to-copy 0))))
  176.           ((fx< (extend-elt next 1) 0)
  177.            (set (k-list) (extend-elt next 0))
  178.            (pop-k-list))
  179.           (else
  180.            (let ((offset (fx- (extend-elt next 1) 1))
  181.                  (forward (extend-header next)))
  182.              (set (extend-elt next 1) offset)
  183.              (move-object (make-pointer forward offset)))))))
  184.  
  185. ;;;   Forward OBJ using copy-pair.  Push the old pair onto the k-list.
  186. ;;; Set the contents of O-LOC to the forwarded pair.  Then recursively
  187. ;;; move the car of the forwarded pair The object in the cdr will
  188. ;;; be moved when the k-list is popped.
  189.  
  190. (define (move-pair obj o-loc)
  191.   (let* ((new (gc-copy-pair obj))
  192.          (xnew (gc-pair->extend new)))
  193.     (set (car obj) (k-list))
  194.     (set (k-list) obj)
  195.     (set (extend-header o-loc) new)
  196.     (move-object xnew)))
  197.  
  198. ;;;   Forward OBJ which is an extend of SIZE longwords with NDESC
  199. ;;; descriptor slots. (Note: Descriptor slots are always the first
  200. ;;; slots of an extend.) O-LOC is the location into which the descriptor
  201. ;;; (+ FORWARDED-OBJECT E-OFF) should be stored.
  202. ;;;   OBJ is forwarded by the primitive COPY-EXTEND which copies the
  203. ;;; old object into the new area.  A forwarding pointer is put in the
  204. ;;; header of the old object.
  205. ;;;   If there are zero descriptors pop the k list.  If there is a
  206. ;;; single descriptor, move it.  If there is more than one descriptor,
  207. ;;; link the object into the K-list, put the number of addresses
  208. ;;; into (extend-elt obj 2), and move the first address.  Closures with
  209. ;;; only one slot are treated as pairs.
  210.  
  211. (define (move-extend obj size ndesc o-loc e-off)
  212.   (let ((new (gc-copy-extend obj size)))
  213.     (set (extend-header o-loc) (make-pointer new e-off))
  214.     (cond ((fx> ndesc 1)
  215.            ;; Push obj onto K list, and set slot-offset.
  216.            (set (extend-elt obj 0) (k-list))
  217.            (set (k-list) obj)
  218.            (let ((last-elt (fx- ndesc 1)))
  219.              (set (extend-elt obj 1) last-elt)
  220.              (move-object (make-pointer new last-elt))))
  221.           ((closure? new) ; OBJ's header is now a forwaring pointer.
  222.            (xcond ((fx= ndesc 0)
  223.                    (move-object new))
  224.                   ((fx= ndesc 1)
  225.                    (set (extend-elt obj 0) (k-list))
  226.                    (set (k-list) (gc-extend->pair obj))
  227.                    (move-object new))))
  228.           (else
  229.            (xcond ((fx= ndesc 0)
  230.                    (pop-k-list))
  231.                   ((fx= ndesc 1)
  232.                    (move-object (make-pointer new 0))))))))
  233.  
  234. ;;;   There are 3 types of templates: code vector, closure internal,
  235. ;;; and dynamic.  All templates are enclosed in other objects.
  236.  
  237. (define (move-template obj o-loc)
  238.   (let ((encloser (template-enclosing-object obj))
  239.         (offset   (template-encloser-offset  obj)))
  240.     (move-internal-object encloser (fx- offset 1) o-loc)))
  241.  
  242. ;;;   This procedure is only called on heap closures since stack closures
  243. ;;; are traced and not copied.  If the closure is internal to another object
  244. ;;; then the enclosing object is moved, otherwise, it is moved as a normal
  245. ;;; extend.
  246.  
  247. (define (move-closure obj o-loc)
  248.   (let ((template (extend-header obj)))
  249.     (cond ((template-internal-bit? template)
  250.            (let ((encloser  (closure-enclosing-object obj))
  251.                  (offset    (closure-encloser-offset obj)))
  252.              (move-internal-object encloser (fx- offset 1) o-loc)))
  253.           (else
  254.            (let* ((ptrs (template-pointer-slots template))
  255.                   (size (fx+ ptrs (template-scratch-slots template))))
  256.              (move-extend obj size ptrs o-loc -1))))))
  257.  
  258. ;;;   Move ENCLOSER which was traced through an internal pointer with an offset
  259. ;;; of OFFSET.  Dispatch on the location and type of ENCLOSER.
  260.  
  261. (define (move-internal-object encloser offset o-loc)
  262.   (let ((header (extend-header encloser)))
  263.     (cond ((and (extend? header)
  264.                 (in-new-space? header))
  265.            (set (extend-header o-loc) (make-pointer header offset))
  266.            (pop-k-list))
  267.           ((bytev? encloser)
  268.            (set (extend-header o-loc)
  269.                 (make-pointer (gc-copy-extend encloser (bytev-cells encloser))
  270.                               offset))
  271.            (pop-k-list))
  272.           ((unit? encloser)
  273.            (let ((size (unit-length encloser)))
  274.              (move-extend encloser size size o-loc offset)))
  275.           ((template? header)
  276.            (let* ((ptrs (template-pointer-slots header))
  277.                   (size (fx+ ptrs (template-scratch-slots header))))
  278.              (move-extend encloser size ptrs o-loc offset)))
  279.           (else
  280.            (gc-error-message "corrupt internal object" o-loc)
  281.            (pop-k-list)))))
  282.  
  283. ;;;   Find out whether a value has been copied into the new heap and return a
  284. ;;; a flag and the new location.  The flag is true if the object was indeed
  285. ;;; retained.  This is a simpler version of MOVE-OBJECT.  Symbols are always
  286. ;;; copied.
  287.  
  288. (define (get-new-copy obj)
  289.   (let ((fxobj (descriptor->fixnum obj)))
  290.     (if (not (and (fx>= fxobj *old-space-begin*)
  291.                   (fx< fxobj *old-space-frontier*)))
  292.         (return t obj)
  293.         (xselect (descriptor-tag obj)
  294.           ((tag/fixnum tag/immediate)
  295.            (return t obj))
  296.           ((tag/pair)
  297.            (if (and (list? (cdr obj))
  298.                     (in-new-space? (cdr obj)))
  299.                (return t (cdr obj))
  300.                (return nil nil)))
  301.           ((tag/extend)
  302.            (let ((header (extend-header obj)))
  303.               (cond ((extend? header)
  304.                      (get-new-extend-copy obj header))
  305.                     ((symbol? obj)
  306.                      (return t (gc-copy-object obj)))
  307.                     (else
  308.                      (return nil nil)))))))))
  309.  
  310. (define (get-new-extend-copy obj header)
  311.   (cond ((template-header? header)   ; 68000 requires this first
  312.          (receive (traced? new-loc)
  313.                   (get-new-copy (template-enclosing-object obj))
  314.            (if traced?
  315.                (return t (make-pointer new-loc
  316.                                        (fx- (template-encloser-offset obj) 1)))
  317.                (return nil nil))))
  318.         ((in-new-space? header)
  319.          (return t (extend-header obj)))
  320.         ((template-internal-bit? header)
  321.          (receive (traced? new-loc)
  322.                   (get-new-copy (closure-enclosing-object obj))
  323.            (if traced?
  324.                (return t (make-pointer new-loc
  325.                                         (fx- (closure-encloser-offset obj) 1)))
  326.                (return nil nil))))
  327.         (else
  328.          (return nil nil))))
  329.  
  330. ;;; Copy an object and return the new pointer
  331.  
  332. (define copy-object-cell
  333.   (make-vector 1))
  334.  
  335. (define (gc-copy-object thing)
  336.   (set (vref copy-object-cell 0) thing)
  337.   (move-object (make-pointer copy-object-cell 0))
  338.   (vref copy-object-cell 0))
  339.  
  340. ;;; Procedures for moving the immediate extends.
  341.  
  342. (define (move-error obj o-loc)
  343.   (ignore obj)
  344.   (gc-error-message "no method for an immediate" o-loc)
  345.   (pop-k-list))
  346.  
  347. (define (move-bytes obj o-loc)
  348.   (set (extend-header o-loc) (gc-copy-extend obj (bytev-cells obj)))
  349.   (pop-k-list))
  350.  
  351. (define (move-foreign obj o-loc)
  352.   (move-extend obj 2 1 o-loc -1))
  353.  
  354. (define (move-general-vector obj o-loc)
  355.   (let ((len (vector-length obj)))
  356.     (move-extend obj len len o-loc -1)))
  357.  
  358. (define (move-unit obj o-loc)
  359.   (let ((len (unit-length obj)))
  360.     (move-extend obj len len o-loc -1)))
  361.  
  362. (define (move-string-slice obj o-loc)
  363.   (move-extend obj 2 1 o-loc -1))
  364.  
  365. (define (move-cell obj o-loc)
  366.   (move-extend obj 1 1 o-loc -1))
  367.  
  368. ;;; Bignums contain only fixnums and thus do not need to be traced.
  369.  
  370. (define (move-bignum obj o-loc)
  371.   (set (extend-header o-loc) (gc-copy-extend obj (bignum-length obj)))
  372.   (pop-k-list))
  373.  
  374. ;;; Stacks must be scanned.
  375.  
  376. (define (move-stack obj o-loc)
  377.   (let ((new (gc-copy-extend obj (stack-length obj))))
  378.     (set (extend-header o-loc) new)
  379.     (real-scan (make-pointer new 0)
  380.                (fx+ (descriptor->fixnum new)
  381.                     (fx- (stack-length new) 1))
  382.                stack-trace-proc)
  383.     t)) ; GC returns from here if there were any stacks copied.
  384.  
  385. ;;; Floats
  386.  
  387. (define (move-double-float obj o-loc)
  388.   (set (extend-header o-loc)
  389.        (gc-copy-extend obj 2))
  390.   (pop-k-list))
  391.  
  392. (define (move-single-float obj o-loc)
  393.   (set (extend-header o-loc)
  394.        (gc-copy-extend obj 1))
  395.   (pop-k-list))
  396.                       
  397. (define (move-vcell obj o-loc)
  398.   (move-extend obj %%vcell-size %%vcell-size o-loc -1))
  399.  
  400. ;;; Weak sets
  401.  
  402. (define (bogus-move-weak-set obj o-loc)
  403.   (move-extend obj 1 1 o-loc -1))
  404.  
  405. (define (move-weak-set obj o-loc)
  406.   (cond ((weak-semaphore-set? obj)
  407.          (move-extend obj 1 1 o-loc -1))
  408.         (else
  409.          (let ((new (gc-copy-extend obj 1)))
  410.            (set (extend-header o-loc) new)
  411.            (set (extend-header new) (gc-weak-set-list))
  412.            (set (gc-weak-set-list) new)
  413.            (pop-k-list)))))
  414.  
  415. ;;; The code for weak alists is just like the code for weak sets.
  416.  
  417. (define (bogus-move-weak-alist obj o-loc)
  418.   (move-extend obj 1 1 o-loc -1))
  419.  
  420. (define (move-weak-alist obj o-loc)
  421.   (cond ((weak-semaphore-set? obj)
  422.          (move-extend obj 1 1 o-loc -1))
  423.         (else
  424.          (let ((new (gc-copy-extend obj 1)))
  425.            (set (extend-header o-loc) new)
  426.            (set (extend-header new) (gc-weak-alist-list))
  427.            (set (gc-weak-alist-list) new)
  428.            (pop-k-list)))))
  429.  
  430. ;;; Weak Tables
  431.  
  432. ;;; WEAK-TABLE-TABLE must be the first slot in a WEAK-TABLE
  433.  
  434. (define (bogus-move-table obj o-loc)
  435.   (move-extend obj 2 2 o-loc -1))
  436.  
  437. (define (move-weak-table obj o-loc)
  438.   (cond ((weak-semaphore-set? obj)
  439.          (move-extend obj 2 2 o-loc -1))
  440.         (else
  441.          (exchange (weak-table-vector obj)
  442.                    (%table-vector (weak-table-table obj)))
  443.          (let ((new (gc-copy-extend obj 2)))
  444.            (set (extend-header o-loc) new)
  445.            (set (extend-header new) (gc-weak-table-list))
  446.            (set (gc-weak-table-list) new)
  447.            (move-object (make-pointer new 0))))))
  448.  
  449. (define (move-weak-cell obj o-loc)
  450.   (set (weak-cell-contents obj) '#f)
  451.   (move-extend obj 1 1 o-loc -1))
  452.  
  453. ;;; Moving immediates
  454.  
  455. (define (move-immediate-object obj o-loc)
  456.   ((vref gc-dispatch-vector (header-type (extend-header obj)))
  457.    obj o-loc))
  458.  
  459. (define gc-dispatch-vector (make-vector %%number-of-immediate-types))
  460.  
  461. (let ((gc-copiers
  462.       `(
  463.         (,header/text           ,move-bytes)
  464.         (,header/general-vector ,move-general-vector)
  465.         (,header/unit           ,move-unit)
  466.         (,header/slice          ,move-string-slice)
  467.         (,header/symbol         ,move-bytes)
  468.         (,header/bytev          ,move-bytes)
  469.         (,header/foreign         ,move-foreign)
  470.         (,header/template       ,move-template)
  471.         (,header/cell           ,move-cell)
  472.         (,header/bignum         ,move-bignum)
  473.         (,header/stack          ,move-stack)
  474.         (,header/double-float   ,move-double-float)
  475.         (,header/single-float   ,move-single-float)
  476.         (,header/vcell          ,move-vcell)
  477.         (,header/weak-set       ,move-weak-set)
  478.         (,header/weak-alist     ,move-weak-alist)
  479.         (,header/weak-table     ,move-weak-table)
  480.         (,header/weak-cell      ,move-weak-cell)
  481.        ; (,header/task           ,move-error)
  482.        ; (,header/true           ,move-error)
  483.        ; (,header/char           ,move-error)
  484.        ; (,header/bitv           ,move-bitv)
  485.        ; (,header/vframe         ,move-error) only on stack
  486.        ; (,header/short-float    ,move-error) unimplemented
  487.         )))
  488.   (vector-fill gc-dispatch-vector move-error)
  489.   (walk (lambda (x) (set (vector-elt gc-dispatch-vector
  490.                                      (fixnum-ashr (car x) 2))
  491.                          (cadr x)))
  492.         gc-copiers))
  493.  
  494. ;;; Three little utilities.
  495.  
  496. (define (gc-copy-pair pair)
  497.   (gc-count-message)
  498.   (let ((new (cons (car pair) (cdr pair))))
  499.     (set (cdr pair) new)
  500.     new))
  501.  
  502. (define (gc-copy-extend obj size)
  503.   (gc-count-message)
  504.   (let ((new (%make-extend (extend-header obj) size)))
  505.     (%copy-extend new obj size)
  506.     (set (extend-header obj) new)
  507.     new))
  508.  
  509. (define (bytev-cells bytev)
  510.   (fixnum-ashr (fx+ (bytev-length bytev) 3) 2))
  511.  
  512. ;;; Statistics and messages.
  513.  
  514. (lset *gc-object-count* 0)       ;;; objects copied up to last message
  515. (lset *gc-click* 0)              ;;; objects copied since last message
  516. (lset *gc-message-frequency* 10000)
  517.  
  518. (define (initialize-gc-stats)
  519.   (set *gc-click* 0)
  520.   (set *gc-object-count* 0))
  521.        
  522. (define-constant (gc-count-message)
  523.   (set *gc-click* (fx+ *gc-click* 1))
  524.   (cond ((fx>= *gc-click* *gc-message-frequency*)
  525.          (set *gc-object-count* (fx+ *gc-object-count* *gc-click*))
  526.          (set *gc-click* 0)    
  527.          (gc-message *gc-object-count*))))
  528.